#include "singleMember.h"
#include "asgkaCreater.h"
#include "singleGroup.h"
#include "global.h"
#include "common.h"
#include "asgkaDelAgreementThread.h"
#include <process.h>

#include <iostream>
using namespace std;

singleGroup::singleGroup()
:m_leader(NULL),
 m_name(""),
 m_my_pubH(NULL),
 m_my_priR(NULL),
 m_my_priX(NULL),
 m_my_groupKeyA(NULL),
 m_my_groupKeyR(NULL),
 m_ciphertext1(NULL),
 m_ciphertext2(NULL),
 m_ciphertext3(NULL),
 m_my_decrypt_key(NULL),
 m_key(NULL)
{
	asgka_malloc(m_key);
}

singleGroup::singleGroup(const std::string &name, singleMember *leader)
:m_leader(leader),
 m_name(name),
 m_my_pubH(NULL),
 m_my_priR(NULL),
 m_my_priX(NULL),
 m_my_groupKeyA(NULL),
 m_my_groupKeyR(NULL),
 m_ciphertext1(NULL),
 m_ciphertext2(NULL),
 m_ciphertext3(NULL),
 m_my_decrypt_key(NULL),
 m_key(NULL)
{
	 asgka_malloc(m_key);
	 addAMember(leader);
}

singleGroup::~singleGroup()
{
	if (m_my_groupKeyA != NULL)
		asgka_free(m_my_groupKeyA);
	if (m_my_groupKeyR != NULL)
		asgka_free(m_my_groupKeyR);
	if (m_ciphertext1 != NULL)
		asgka_free(m_ciphertext1);
	if (m_ciphertext2 != NULL)
		asgka_free(m_ciphertext2);
	if (m_ciphertext3 != NULL)
		asgka_free(m_ciphertext3);
	if (m_key != NULL)
		asgka_free(m_key);
	if (m_my_decrypt_key != NULL)
		asgka_free(m_my_decrypt_key);

	// Delete all the pointer
	std::map<std::string, singleMember *>::iterator it = m_member_list.begin();
	while (it != m_member_list.end())
	{
		it->second->leftAGroup(m_name);
		m_member_list.erase(it++);
	}
}

void singleGroup::setName(const std::string &name)
{
	m_name = name;
}

void singleGroup::setLeader(singleMember *leader)
{
	if (m_leader == NULL)
		m_leader = leader;
}

int singleGroup::setGroupKeyA(c_asgka_element content)
{
	if (m_my_groupKeyA == NULL)
		asgka_malloc(m_my_groupKeyA);
	return strcpy_s(m_my_groupKeyA, LENGTH, content);
}

int singleGroup::setGroupKeyR(c_asgka_element content)
{
	if (m_my_groupKeyR == NULL)
		asgka_malloc(m_my_groupKeyR);
	return strcpy_s(m_my_groupKeyR, LENGTH, content);
}

int singleGroup::setCiphertext1(c_asgka_element content)
{
	if (m_ciphertext1 == NULL)
		asgka_malloc(m_ciphertext1);
	return strcpy_s(m_ciphertext1, LENGTH, content);
}

int singleGroup::setCiphertext2(c_asgka_element content)
{
	if (m_ciphertext2 == NULL)
		asgka_malloc(m_ciphertext2);
	return strcpy_s(m_ciphertext2, LENGTH, content);
}

int singleGroup::setCiphertext3(c_asgka_element content)
{
	if (m_ciphertext3 == NULL)
		asgka_malloc(m_ciphertext3);
	return strcpy_s(m_ciphertext3, LENGTH, content);
}

int singleGroup::setPubH(c_asgka_element content)
{
	if (m_my_pubH == NULL)
		asgka_malloc(m_my_pubH);
	return strcpy_s(m_my_pubH, LENGTH, content);
}

int singleGroup::setPriR(c_asgka_element content)
{
	if (m_my_priR == NULL)
		asgka_malloc(m_my_priR);
	return strcpy_s(m_my_priR, LENGTH, content);
}

int singleGroup::setPriX(c_asgka_element content)
{
	if (m_my_priX == NULL)
		asgka_malloc(m_my_priX);
	return strcpy_s(m_my_priX, LENGTH, content);
}

int singleGroup::setPlaintext(c_asgka_element content)
{
	if (m_key == NULL)
		asgka_malloc(m_key);
	return strcpy_s(m_key, LENGTH, content);
}

int singleGroup::setDecryptKey(c_asgka_element content)
{
	if (m_my_decrypt_key == NULL)
		asgka_malloc(m_my_decrypt_key);
	return strcpy_s(m_my_decrypt_key, LENGTH, content);
}

long singleGroup::getGroupID() const
{
	return m_id;
}

int singleGroup::getGroupPopulation() const
{
	return m_member_list.size();
}

std::string singleGroup::getGroupName() const
{
	return m_name;
}

singleMember *singleGroup::getGroupLeader() const
{
	return m_leader;
}

const std::map<std::string, singleMember *> *singleGroup::getAddrofMemberlist() const
{
	const std::map<std::string, singleMember *> *p = &m_member_list;
	return p;
}

c_asgka_element singleGroup::getAddrofGroupKeyA() const
{
	c_asgka_element p = m_my_groupKeyA;
	return p;
}

c_asgka_element singleGroup::getAddrofGroupKeyR() const
{
	c_asgka_element p = m_my_groupKeyR;
	return p;
}

c_asgka_element singleGroup::getAddrofCiphertext1() const
{
	c_asgka_element p = m_ciphertext1;
	return p;
}

c_asgka_element singleGroup::getAddrofCiphertext2() const
{
	c_asgka_element p = m_ciphertext2;
	return p;
}

c_asgka_element singleGroup::getAddrofCiphertext3() const
{
	c_asgka_element p = m_ciphertext3;
	return p;
}

c_asgka_element singleGroup::getAddrofPlaintext() const
{
	c_asgka_element p = m_key;
	return p;
}

c_asgka_element singleGroup::getAddrofDecryptKey() const
{
	c_asgka_element p = m_my_decrypt_key;
	return p;
}

c_asgka_element singleGroup::getAddrofPubH() const
{
	c_asgka_element p = m_my_pubH;
	return p;
}

c_asgka_element singleGroup::getAddrofPriR() const
{
	c_asgka_element p = m_my_priR;
	return p;
}


c_asgka_element singleGroup::getAddrofPriX() const
{
	c_asgka_element p = m_my_priX;
	return p;
}

singleMember *singleGroup::getMemberByName(const std::string &name) const 
{
	std::map<std::string, singleMember *>::const_iterator cit = m_member_list.find(name);
	if (cit != m_member_list.end())
		return cit->second;
	return NULL;
}

void singleGroup::addAMember(singleMember *member)
{
	// Nullify all the ciphertexts
	asgka_free(m_ciphertext1);
	asgka_free(m_ciphertext2);
	asgka_free(m_ciphertext3);
	m_ciphertext1 = NULL;
	m_ciphertext2 = NULL;
	m_ciphertext3 = NULL;

	if (!isAMember(member->getMemberName()))
	{
		cout << member->getMemberName() << " joined the group!" << endl; 
		m_member_list.insert(stomvalType(member->getMemberName(), member));
		member->joinedAGroup(m_name);
		cout << "Added a member: " << member->getMemberName() << endl;
	}
}

void singleGroup::deleteAMember(const std::string &name)
{
	// Nullify all the ciphertexts
	asgka_free(m_ciphertext1);
	asgka_free(m_ciphertext2);
	asgka_free(m_ciphertext3);
	m_ciphertext1 = NULL;
	m_ciphertext2 = NULL;
	m_ciphertext3 = NULL;

	std::map<std::string, singleMember *>::iterator it = m_member_list.find(name);
	if (it != m_member_list.end())
	{
		it->second->leftAGroup(m_name);
		m_member_list.erase(it);
	}
}

void singleGroup::generateMemberList(std::map<std::string, u_long> &member_list) const
{
	std::map<std::string, singleMember *>::const_iterator it = m_member_list.begin();

	for (; it != m_member_list.end(); it++)
	{
		member_list.insert(stouvalType(it->first, it->second->getNetAddr()));
	}
}

bool singleGroup::isAMember(const std::string &name) const
{
	std::map<std::string, singleMember *>::const_iterator it = m_member_list.find(name);
	return (it != m_member_list.end());
}

int singleGroup::sendMessagetoGroup(const char *buf, int length) const
{
	return 0;
}

int singleGroup::decryptMessage(char *plainbuf, const char *ciphertext, int length) const
{
	return 0;
}

bool singleGroup::isAllXigamaOK()
{
	std::map<std::string, singleMember *>::iterator it = m_member_list.begin();

	bool flag = true;
	for (;it != m_member_list.end(); it++)
	{
		if (localname.compare(it->first) == 0)
			continue;
		if (!it->second->isXigamaOK(m_name))
		{
			flag = false;
			break;
		}
	}

	return flag;
}

bool singleGroup::isAllAOK()
{
	std::map<std::string, singleMember *>::iterator it = m_member_list.begin();

	bool flag = true;
	for (;it != m_member_list.end(); it++)
	{
		if (localname.compare(it->first) == 0)
			continue;
		if (!it->second->isPubAOK(m_name))
		{
			flag = false;
			break;
		}
	}

	return flag;
}

bool singleGroup::isAllHOK()
{
	std::map<std::string, singleMember *>::iterator it = m_member_list.begin();

	bool flag = true;
	for (;it != m_member_list.end(); it++)
	{
		if (localname.compare(it->first) == 0)
			continue;
		if (!it->second->isPubHOK(m_name))
		{
			flag = false;
			break;
		}
	}

	return flag;
}

bool singleGroup::isAllROK()
{
	std::map<std::string, singleMember *>::iterator it = m_member_list.begin();

	bool flag = true;
	for (;it != m_member_list.end(); it++)
	{
		if (localname.compare(it->first) == 0)
			continue;
		if (!it->second->isPubROK(m_name))
		{
			flag = false;
			break;
		}
	}

	return flag;
}

bool singleGroup::isCipherTextOK()
{
	bool flag = true;
	flag = flag && (m_ciphertext1 != NULL);
	flag = flag && (m_ciphertext2 != NULL);
	flag = flag && (m_ciphertext3 != NULL);
	return flag;
}

